home *** CD-ROM | disk | FTP | other *** search
- ; 386POWER v1.00 is part of the public domain portion
- ; of the XGE system
- ; XGE == eXtended Game Engine
- ; see 386power.doc for more info & credits
-
- .386p
-
- ; Use int 33h to call a v86 interrupt routine from protected mode
- ; Use int 32h to call a 32bit procedure (16bit to 32bit & back)
- ; Use int 32h to call a 16bit v86 procedure (32bit to 16bit & back)
-
- ; respect this segment order or you'll get troubles
- code16 segment para public use16
- code16 ends
- code32 segment para public use32
- code32 ends
- codeend segment para stack use32 'stack'
- codeend ends
-
- include 386power.inc
-
- ;=======================================
- ; Real mode and 16bit 386 code
- ;=======================================
- code16 segment para public use16
- assume cs:code16, ds:code16
- org 0
- align byte
-
- ; this macro is used to produce debug messages under real mode
- say macro t_item
- push dx
- push ax
- mov dx, offset t_item
- mov ah,09
- int 21h
- pop ax
- pop dx
- endm
-
- Test386 macro
- ; Detect if current processor is a 386
- pushf ; save flags
- xor ah,ah ; pseudo_flags tutti azzerati
- push ax ;
- popf ; flags tutte azzerate
- pushf ;
- pop ax ; recupera flags
- and ah,0f0h ; elimina CARRY,PARITY
- cmp ah,0f0h ;
- jz NotA386 ; ci sono flag superiori, il 386 non li maschera
- mov ah,0f0h ; riprova con i bit4..bit7 posti ad 1
- push ax ;
- popf ; analogo
- pushf ;
- pop ax ; idem
- popf ; reload flags
- and ah,0f0h ;
- jnz Is386 ; alcuni flags ci sono, il 386 non li maschera
- NotA386:
- mov dx,offset em0_no386
- jmp exit16err
- Is386:
- endm
-
- DOSRAMTOP = 0002
-
- Boot16: ; DOS EXTENDER starts here and kicks program into 386 protected mode
- mov ax,cs
- mov ds,ax
- mov ax,0003 ; set 80x25 text mode
- int 10h ;
-
- ; show who holds the copyrights etc. etc.
- mov dx,offset _386power_info
- mov ah,09
- int 21h
-
- Test386
- say msg_386
-
- pushf
- pop ax
- mov ds:V86F,ax
- say msg_gints
- ; copy old ints before kicking into the prot. mode
- mov si,offset _OldInt
- mov ax,03500h ; get interrupt vectors
- push es
- getints:
- int 21h
- mov [si],bx
- add si,2
- mov [si],es
- add si,2
- inc al
- jnz getints
- pop es
-
- ; install int 32h handler for
- ; real_mode TO protected_mode calls
- ; (available only from the real mode side of 386Powered programs)
- ; WARNING! This real->prot mode proc call doesn't pass virtual
- ; register values.
- mov ax,02532h
- mov dx,offset REAL_VCPI_DPMI_INT32
- ; ds:dx == ptr to new int handler
- int 21h
- say msg_typeslow
- ; Now set typematic rate to the lowest values
- mov ax,0305h ; typematic_rate set_rate
- mov bx,001Fh ; 00 == 250msec delay_value 1F == 2char/sec repeat_rate
- int 16h
-
- cli ; turn off interrupts while initializing
- cld ; The only way is UP! (er.. the default is up)
-
- ; Now it's time to convert pointers from
- ; seg:ofs to LINEAR or EXTENDED
-
- mov ax,es ; PSP LINEAR OFFSET
- movzx eax,ax ;
- shl eax,4 ;
- mov ds:_PSPBase,eax ;
-
- mov eax,code16 ; CODE16 LINEAR ADDRESS
- shl eax,4 ;
- mov ds:_Code16Base,eax ;
-
- mov ebx,code32 ; CODE32 LINEAR ADDRESS
- shl ebx,4 ;
- mov ds:_Code32Base,ebx ;
-
- or dword ptr ds:GDTcode16[2],eax ; SET UP code16 and data16 GTD entries
- or dword ptr ds:GDTdata16[2],eax ;
-
- or dword ptr ds:GDTcode32[2],ebx ; SET UP code32 and data32 GTD entries
- or dword ptr ds:GDTdata32[2],ebx ;
-
- add dword ptr ds:s16_GDTaddr[2],ebx ; SET UP GTD descriptor
-
- mov eax,codeend ; ebx == code32 linear address
- shl eax,4 ; eax == codeend linear address
- sub eax,ebx ; eax == codeend offset from code32
- mov ds:_LoMemBase,eax ; set lomembase ( it grows up )
- mov ds:StackBaseAddress,eax ; set stackbase ( it grows down )
-
- movzx eax,word ptr es:[DOSRAMTOP] ; get low memory size in paragraphs
- shl eax,4 ; para to bytes
- sub eax,ebx ; code32 relative offset
- mov ds:_LoMemTop,eax ; set low memory top
- mov dx,offset em1_no_lomem
- cmp eax,00
- jg ramright
- jmp exit16err
- ramright:
- mov eax,STACKSIZE*16 ; set up stack frame
- call InitAlloc ;
-
- push es ; save PSP seg (DPMI test may kill ES)
- pop fs ;
-
- say msg_DPMItest
- ; now TEST FOR DPMI
- mov ax,1687h ; Get Real-to-Protected-Mode Switch entry point:
- ;
- ; The entry point you get must be called ONLY ONCE
- ; FOR THE FIRST SWITCH to DPMI protected mode.
- ; Input:
- ; AX = 1687h
- ; Output:
- ; AX = 0 if function successfull
- ; BX = DPMI flags
- ; bit 0: 0 = 16bit program support only
- ; 1 = 32bit program support
- ; bit 1..15 NOT USED
- ; CL = processor type 02h= 80286
- ; 03h= 80386
- ; 04h= 80486
- ; 05h= Pentium ?
- ; 06h..0FFh = not used
- ; DH = DPMI version major number (binary)
- ; DL = DPMI version minor number (binary)
- ; [386power fully supports DPMI 0.9 and 1.0]
- ; SI = number of paragraphs required for
- ; DPMI host private data (it may be 0)
- ; ES:DI = segment:offset of procedure to call
- ; to enter protected mode
-
- int 2fh ;
- or ax,ax ;
- jz StartDPMI ; Go DPMI if present
-
- say msg_VCPItest
- ; Not DPMI, try VCPI, this is a lot more complex
- mov eax,0
- mov gs,ax
- cmp eax, gs:(4*67h) ; NULL vector ?
- je short NotIntoVCPI
- mov ax,0de00h ;
- int 67h ; Call VCPI INSTALLATION CHECK
- or ah,ah ;
- jnz short NotIntoVCPI ; if (ah != 0) it isn't VCPI
- jmp StartVCPI
- NotIntoVCPI:
-
- ; No other VMM is supported
- mov dx,offset emN_VMM
- jmp exit16err
-
- ; teletyper calls the dos function int 21h, ah=09
- ; under DPMI once the GS segment is set up (l
-
- teletyper:
- ; DPMI teletyper
- pushad
- push es
- mov es,ds:_EXIT_DATA_SEL
- mov ds:V86ds,code16
- mov ds:V86edx,edx
- mov ds:V86ah,9
- mov bx,0021h
- mov cx,0
- mov edi, offset ds:V86edi
- mov ax,300h
- int 31h
- pop es
- popad
- ret
-
- psay macro d_item
- push edx
- mov edx, offset code16:d_item
- call teletyper
- pop edx
- endm
-
- ;------------------------------------------------------------------------------
- ; 16 bit common system data
-
- CR = 0dh
- LF = 0ah
-
- ; debug messages
- msg_386 db ' Found 386 CPU or higher',CR,LF,'$'
- msg_DPMItest db ' Checking DPMI',CR,LF,'$'
- msg_VCPItest db ' Checking VCPI',CR,LF,'$'
- msg_typeslow db ' Slowing down typematic rate',CR,LF,'$'
- msg_type db ' Setting default typematic rate',CR,LF,'$'
- msg_gints db ' Saving DOS interrupt table',CR,LF,'$'
- msg_rints db ' Restoring DOS interrupt table',CR,LF,'$'
- msg_end db ' Terminating program ... CIAO! See you later.',CR,LF,'$'
- msg_DPMImem db ' Calling DPMI function 501h to allocate extended memory'
- db CR,LF,'$'
- msg_DPMIwin db ' Extended memory allocated',CR,LF,'$'
- msg_DPMIirq db ' Setting new DPMI irq handlers',CR,LF,'$'
- msg_VCPIfree db ' Freeing pages allocated thru VCPI',CR,LF,'$'
-
- emN_VMM db ' 386Power found no VCPI or DPMI manager installed',CR,LF
- db ' Check if you have at least a 386 Extended Memory Manager',CR,LF
- db ' properly configurated and then try again',CR,LF
- db ' this program should run fine with EMM386, QEMM, 386MAX ',CR,LF
- db ' or Microsoft Windows running in 386 enhanced mode',CR,LF,'$'
-
- ; hex ->ascii translation table
- emT_hextable db '0123456789ABCDEF'
-
- ; standard message
- emX_stderr db '[ See file 386ERROR.TXT for more info ]',7,CR,LF,'$'
-
- ; error strings
- em0_no386 db 'Error 00: 386 COMPATIBLE PROCESSOR NOT DETECTED!',CR,LF,'$'
- em1_no_lomem db 'Error 01: NOT ENOUGH MEMORY UNDER 640KB!',CR,LF,'$'
- em2_unkV86 db 'Error 02: UNKNOWN MEMORY MANAGER DRIVES V86 MODE!',CR,LF,'$'
- em3_no_himem db 'Error 03: NOT ENOUGHT MEMORY ABOVE 1MB!',CR,LF,'$'
- em4_noA20 db 'Error 04: A20 ADDRESS LINE NOT ENABLED!',CR,LF,'$'
- em5_hifault db 'Error 05: FAILED ALLOCATION OF MEMORY ABOVE 1MB!',CR,LF,'$'
- em6_PICfault db 'Error 06: VCPI P.I.C. INT MAPPED ON 386POWER INTS',CR,LF,'$'
- em7_noDPMI32 db 'Error 07: NOT A 32 BIT DPMI HOST!',CR,LF,'$'
- em8_DPMIdesc db 'Error 08: NOT ENOUGH DPMI DESCRIPTORS!',CR,LF,'$'
- em9_DPMImod db 'Error 09: CANNOT MODIFY DPMI DESCRIPTORS!',CR,LF,'$'
- emA_FIX db 'Error 0A: VCPI HAS NOT ENOUGH PAGES AVAILABLE!',CR,LF,'$'
- emB_lowDPMI db 'Error 0B: DPMI API IS OLDER THAN DPMI 0.9',CR,LF,'$'
- emC_linear db 'Error 0C: LINEAR MEMORY SPACE EXAUSTED',CR,LF,'$'
- emD_phys db 'Error 0D: PHISYCAL MEMORY SPACE EXAUSTED',CR,LF,'$'
- emE_backing db 'Error 0E: BACKING STORAGE EXAUSTED',CR,LF,'$'
- emF_handle db 'Error 0F: INVALID HANDLE',CR,LF,'$'
- em10_invalid db 'Error 10: INVALID PARAMETER VALUE',CR,LF,'$'
- em11_EqPIC db 'Error 11: P.I.C. MAP ON SAME INTERRUPT SLOT',CR,LF,'$'
-
- _386power_info db CR,LF
- db '┌────────────────────────────────────────────────────────────┐',CR,LF
- db '│ 386Power Dos-Extender 386P Revision 0.999 BETA │',CR,LF
- db '│ │',CR,LF
- db '│ This is a public domain dos-extender module │',CR,LF
- db '│ designed for a VCPI/DPMI interface to protected mode. │',CR,LF
- db '│ You need a VCPI or DPMI manager to run this. │',CR,LF
- db '│ │',CR,LF
- db '│ (c) Copyright Lorenzo Micheletto MCHLNZ67T19C890A │',CR,LF
- db '│ All rights reserved, except the portions of 386Power │',CR,LF
- db '│ based on the source code of the PMODE dos-extender │',CR,LF
- db '│ by Thomas "Tran" Pytel. │',CR,LF
- db '│ See the 386Power documentation for explanations. │',CR,LF
- db '│ │',CR,LF
- db '└────────────────────────────────────────────────────────────┘',CR,LF
- db CR,LF,'$'
-
- nullint db 0cfh ; IRET instruction
- exitrout dw exit ; exit routine, modified if XMS, VCPI
-
- ;=============================================================================
- ; 16 bit DPMI system data
-
- align dword
- d16_Fast16_To_32 dd ? ; switch from 16bit to 32bit
- d16_SaveRestoreState dd ? ; save/restore state addr
- align word
- d16_EnterDPMI dw ?,? ; DPMI switch to protected mode (16bit)
- d16_SavStackOfs dw ? ; current saved stack offset
- d16_SavStackSeg dw ? ; current saved stack segment
- d16_PSPSel dw ? ; PSP selector (use it in prot. mode)
- d16_DosEnvSegSel dw ? ; ENVIRONMENT selector
-
- d16_nintoff dw d32_irq0,d32_irq1,d32_irq2,d32_irq3,d32_irq4,d32_irq5,d32_irq6,d32_irq7
- dw d32_irq8,d32_irq9,d32_irqa,d32_irqb,d32_irqc,d32_irqd,d32_irqe,d32_irqf
- dw d32_int33,d32_int32
-
- ;-----------------------------------------------------------------------------
- ; 16bit VCPI system data
-
- ; VCPI EMS DATA
-
- ; VCPI PAGE DIRECTORY DATA
- align word
- v16_PageDirSeg dw ? ; seg of page directory
- v16_PageBase dw 0 ; first page of himem (*4)+1000h
- v16_PageTop dw 0 ; top page of himem (*4)+1000h
-
- ;------------------------------------------------------------------------------
- align word
- ; VCPI mode-switch data
- v16_sw_cr3 dd ? ; new CR3 for 386P (physical)
- v16_sw_gdtaddrptr dw s16_GDTaddr,0 ; ptr to GDT data for 386P
- v16_sw_idtaddrptr dw s16_IDT32addr,0 ; ptr to IDT data for 386P
- v16_sw_ldtsel dw 0 ; don't need LDTs
- v16_sw_trsel dw 30h ; task state segment selector
- v16_sw_dest dd ? ; start in 386P EIP
- dw 20h ; start in 386P CS
-
- v16_b0b1b2b3 dw 000Ah ; Ah!
-
- v16_VCPIsys dd offset v16_sw_cr3
-
- ;----------------------------------------------------------------------------
- ; 16 bit POWER mode system data
-
- align word
-
- s16_IDT32addr dw 19fh, ?,? ; 32bit IDT address,limit
- s16_GDTaddr dw 04fh, GDT,0 ; 32bit GDT address,limit
-
- s16_OldPICInt dw 7008h ; old PIC vals, maybe modified in VCPI
- s16_Int_to_replace_ctr db 33h ; number of int vects needed -1, ditto
-
- ; Warning! this data is packet into 16bit words!!!!
- ; (Oh! What i do to gain memory space)
- s16_idt32handler dw s32_irq0,s32_irq1,s32_irq2,s32_irq3,s32_irq4,s32_irq5
- dw s32_irq6,s32_irq7,s32_irq8,s32_irq9,s32_irqa,s32_irqb
- dw s32_irqc,s32_irqd,s32_irqe,s32_irqf
- dw s32_int33,s32_int32,s32_int31
- dw s32_exc0,s32_exc1,s32_exc2,s32_exc3,s32_exc4,s32_exc5
- dw s32_exc6,s32_exc7,s32_exc8,s32_exc9,s32_exca,s32_excb
- dw s32_excc,s32_excd,s32_exce
- align dword
-
- ; table containing interrupt vectors as found at 386P initialization
- _OldInt dd 0
- dd 256 dup(0)
-
- align byte
- ;------------------------------------------------------------------------------
-
- InitAlloc:
- ; Allocate low memory or abort. (called from initialization code)
- ; EAX=space to allocate
- add eax,ds:_LoMemBase
- mov ebx,ds:_LoMemTop
- cmp eax,ebx ; gone above _LoMemTop ?
- ja short noinitmem ;
- mov ecx,eax
- xchg eax,ds:_LoMemBase
- sub ebx,ecx
- cmp ebx,LOWMIN*1024 ; gone above lower memory limit of
- jb short noinitmem ; free memory reserved for program data ?
- ret
- noinitmem:
- mov dx,offset em1_no_lomem
- ; join error report & exit routine
- exit16err:
- mov ah,09 ; Tell what's gone wrong and get out
- int 21h
- mov dx,offset emX_stderr
- mov ah,09
- int 21h
- jmp exitrout
-
- exit: ; Good Old terminate program function (default exitrout)
- ; for real mode termination or the final VCPI shutdown
- ; (DPMI shutdown goes thru a different route)
- ; restore interrupts before getting out
- say msg_rints
- mov si,offset _OldInt
- mov ax,02500h
- push ds
- setints:
- mov dx,cs:[si]
- add si,2
- mov ds,cs:[si]
- add si,2
- int 21h
- inc al
- jnz setints
- pop ds
- say msg_type
- ; restore default typematic rate
- ; now set typematic rate to the default values
- mov ax,0305h ; typematic_rate set_rate
- mov bx,000Ch ; 00 == 250msec delay_value 0C == 10char/sec repeat_rate
- int 16h
- sti
- say msg_end
- mov ax,4c00h ; terminate this program
- int 21h
-
- ; 16 bit common system code starts here
-
- ; INTREAL & CALLREAL
- ; temporary INT to real mode OR temporary CALL FAR to real mode.
- ; CALLS TO INTREAL OR CALLREAL ARE PERFORMED FROM CODE32 SWITCHPOINTS
- ; SO WHEN THE CPU GETS HERE THE MODE SWITCH HAS ALREADY BEEN DONE.
-
- intreal: ; temporary int to real mode , NOW WE ARE In 16bit mode
- cli ; disable interrupts, they will stay disabled
- ; even after the call to the real mode int
- pushf ; save flags
- push cs ; push RETURN address on stack
- push offset ir_done ; to get back from real mode
- mov eax,cs:tempaddr ;
- push dword ptr cs:[eax*4+_OldInt] ; push old int address seg:ofs
- mov fs,cs:V86fs ; load Vregs
- mov gs,cs:V86gs ;
- mov eax,cs:V86eax ;
- mov ecx,cs:V86ecx ;
- mov edx,cs:V86edx ;
- mov ebx,cs:V86ebx ;
- mov esi,cs:V86esi ;
- mov edi,cs:V86edi ;
- mov ebp,cs:V86ebp ;
- cli ; interrupts will need int flag disabled
- retf ; this retf jumps to the seg:ofs in tempaddr
- ir_done:
- pushf ; save returned flags
- pop cs:V86F ;
- mov cs:V86eax,eax
- mov cs:V86ecx,ecx
- mov cs:V86edx,edx
- mov cs:V86ebx,ebx
- mov cs:V86esi,esi
- mov cs:V86edi,edi
- mov cs:V86ebp,ebp
- mov cs:V86ds,ds
- mov cs:V86es,es
- mov cs:V86fs,fs
- mov cs:V86gs,gs
- jmp IREAL_TERMINATOR
-
- callreal: ; temporary far call to real mode , NOW in 16bit mode
- push cs ; push RETURN address on stack
- push offset ic_done ; to get back from real mode
- mov fs,cs:V86fs ; load Vregs
- mov gs,cs:V86gs ;
- mov eax,cs:V86eax ;
- mov ecx,cs:V86ecx ;
- mov edx,cs:V86edx ;
- mov ebx,cs:V86ebx ;
- mov esi,cs:V86esi ;
- mov edi,cs:V86edi ;
- mov ebp,cs:V86ebp ;
- push cs:tempaddr ; push address to call (32 bit seg:ofs )
- sti ; make sure interrupts are enabled
- retf ; this retf jumps to the seg:ofs in tempaddr
- ic_done:
- cli ; disable interrupts on return
- pushf ; save flags
- pop cs:V86F ;
- mov cs:V86eax,eax
- mov cs:V86ecx,ecx
- mov cs:V86edx,edx
- mov cs:V86ebx,ebx
- mov cs:V86esi,esi
- mov cs:V86edi,edi
- mov cs:V86ebp,ebp
- mov cs:V86ds,ds
- mov cs:V86es,es
- mov cs:V86fs,fs
- mov cs:V86gs,gs
- IREAL_TERMINATOR:
- mov al,cs:_386Man
- or al,al ; VCPI ?
- jne irToDPMI32
-
- irToVCPI32: ; VCPI return to 386P
- mov eax,offset s32_int3_d ; jump to end of 386P INT32/33
- jmp VCPI_SWITCH
-
- irToDPMI32: ; DPMI return to 386P
- mov ebx,cs:d32_SavStackOfs ;
- mov dx,cs:d32_SavStackSel ; get 386P stack in dx:ebx
-
- mov cx,dx ; cx = current stack seg. (same of 386P)
- mov si,cs:_SelCode ; si = new code sel
- mov edi,offset d32_16done ; edi = new code offset
- mov ax,cs:_SelData ; ax = new data sel
- jmp cs:d16_Fast16_To_32 ; mode switch routine
-
-
- ;=============================================================================
- ; SET INT SLOTS TABLE
- ; BL=low PIC val, BH=high PIC val, DI->int slot table
- ; THE FIRST 16 INT SLOTS ARE THE IRQ INT SLOTS
-
- setintslots: ; set int slot table
- push cx
- mov cx,8
- setpicints:
- mov [di],bl
- mov [di+8],bh
- inc di
- add bx,0101h
- loop setpicints
- pop cx
- ret
-
- ;==============================================================================
- ; 16 bit DPMI system code
-
-
- REAL_VCPI_DPMI_INT32: ; DPMI/VCPI REAL MODE INT32: EDX=offset to call
- pushad
- push ds
- push es
- push fs
- push gs
-
- pushfd ; push 32bit flag dword
- cli
- mov ax,cs
- mov ds,ax
- mov ds:tempaddr,edx
- pop eax ; restore 32bit flag dword
- and eax,512 ; select bit 9 (interrupt flag)
- mov ds:DV_INT32INTFLAG,eax ; stick it into the switch flag
-
- push d16_SavStackOfs
- push d16_SavStackSeg
- movzx ebx,ds:nextmodestack
- lea eax,[ebx-STACKSLOT*16]
- mov ds:nextmodestack,ax
- add ebx,ds:StackBaseAddress
- sub sp,ds:d32_StateBufferSize
- mov d16_SavStackOfs,sp
- mov d16_SavStackSeg,ss
-
- ; VCPI/DPMI
- cmp cs:_386Man,IS_VCPI
- je VCPI_Int32_From_Real_Mode
- ; DPMI_Int32_From_Real_Mode:
- mov ax,ss
- mov es,ax
- mov di,sp
- xor al,al
- call d16_SaveRestoreState
- mov ax,ds:_SelData
- mov cx,ax
- mov dx,ax
- mov si,ds:_SelCode
- mov edi,offset d32_call386P
- jmp d16_Fast16_To_32
- DPMI_Return_Int32R:
- mov di,sp
- mov al,1
- call d16_SaveRestoreState
- add sp,ds:d32_StateBufferSize
- ;-----------------------------------------------------------------------------
- DONE_INT32R_DPMI_VCPI: ; done from DPMI or VCPI
- pop d16_SavStackSeg
- pop d16_SavStackOfs
- add ds:nextmodestack,STACKSLOT*16
- pop gs
- pop fs
- pop es
- pop ds
- popad
- iret
-
- ;--------------------------------------------------------------------------
- ; DPMI 16 bit TERMINATION ROUTINE
-
- d16_retreal: ; DPMI TERMINATE
-
- ; Restore interrupts grabbed by DPMI interface
- psay msg_rints
- mov ax,0205h
- mov edi,17 ; 16 ints for irq + int 33h & int 32h
- d16_int_restore:
- mov bl,ds:intslotnum[di]
- lea ebp,[edi*2+edi]
- mov edx,dword ptr ds:d32_OldInts[ebp*2]
- mov cx,word ptr ds:d32_OldInts[ebp*2+4]
- int 31h
- sub di,1
- jnc d16_int_restore
- jmp d16_exit
-
- d16_exit16err: ; DPMI Exit with error message
- mov ds:V86ds,code16
- mov ds:V86ah,9
- mov ax,0300h
- mov bx,0021h
- mov cx,0
- mov edi,offset ds:V86edi
- push ds
- pop es
- int 31h
- d16_exit: ; DPMI exit to real mode
- mov es,d16_PSPSel ; restore env selector
- mov ax,d16_DosEnvSegSel
- mov es:[2ch],ax
-
- ; TERMINATE PROGRAM
- ; but restore interrupts before getting out
- ; using the DPMI API function
- mov si,offset _OldInt
- mov ax,02501h
- mov bl,00
- dsetints:
- mov dx,cs:[si]
- add si,2
- mov cx,cs:[si]
- add si,2
- int 31h
- inc bl
- jnz dsetints
- ; Now terminate program
- sti
- psay msg_type
- push es
- ; Restore default typematic rate
- mov ds:V86ax,0305h ; typematic_rate set_rate
- mov ds:V86bx,000Ch ; 00 = 250msec delay_value 0C = 10char/sec repeat_rate
- mov bx,0016h
- mov cx,0
- mov ax,300h
- mov es,cs:_SelData
- mov edi, offset code32:V86edi
- int 31h
- pop es
- psay msg_end
- ; la chiamata diretta alla funzione 4ch produceva dei casini
- ; stranissimi sotto windows, quindi...
- mov ax,4c00h
- int 21h
-
- StartDPMI: ; DPMI initialization
- or ds:_386Man,IS_DPMI ; set system type DPMI byte
-
- test bl,1 ; must be 32bit DPMI
- mov dx,offset em7_noDPMI32 ;
- jz exit16err ;
- mov d16_EnterDPMI[0],di ; store enter protected mode addr
- mov d16_EnterDPMI[2],es ;
-
- push word ptr fs:[2ch] ; preserve environment segment
- ; located into PSP
-
- ; NOW GET READY TO ENTER 16BIT PROTECTED MODE
- ; remember, SI = paragraphs needed for DPMI private data
-
- movzx eax,si ; get mem for DPMI block
- shl eax,4 ;
- call InitAlloc ;
- shr eax,4 ;
- add ax,code32 ;
- mov es,ax ; es:0000 = base of DPMI private data
-
- mov ax,0001h ; This is a 32bit application
- ; so turn on 32bit register interface
-
- call dword ptr d16_EnterDPMI
-
- ; NOW IN 16 BIT PROTECTED MODE
- ; PSP:[2ch] now is a SELECTOR to the environment space
- ; cs,ds,ss are now SELECTORS equivalent to their
- ; previous real-mode segment values.
- ; es conatins the PSP selector
- ; fs,gs are set to zero
-
- cli ; Better don't trust DPMI , clear interrupts again
-
- mov dx,offset em8_DPMIdesc ;
- jc exit16err ; Got a descriptor ?
-
- mov ds:V86dx,dx ; prepare for abort if any error lurks
-
- pop ax ; swap old16_env16_seg with selector
- xchg ax,es:[2ch] ; now pspa+2ch == environment REAL segment
- ; we use this trick because VCPI,XMS&POWER
- ; startup code doesn't set up selectors for PSP
-
- mov d16_DosEnvSegSel,ax ; DPMI ENVIRONMENT selector
-
- mov d16_PSPSel,es ; store PSP selector
-
- mov ds:_EXIT_DATA_SEL,ds ;
- mov ds:_EXIT_SEL,cs ;
- mov ds:_EXIT_OFS,offset d16_retreal ; set program termination data
-
- mov ds:_SetIRQ,offset d32_setirq ; set new IRQ managers
- mov ds:_GetIRQ,offset d32_getirq ;
-
- push ds ; no more need for PSP segment
- pop es ;
-
- ; MUST ASK DPMI FOR VALID SELECTORS
- mov ax,0003 ; get selector increment value
- int 31h ;
- mov bx,ax ;
-
- mov ax,0000 ; get base selector for a list of 3 selectors
- mov cx,3 ; cx= number of selector to allocate in LDT
- int 31h ;
-
- jc d16_exit16err
- ; set up descriptors
- ; bx= selector increment , ax = first selector value
-
- ; INITIALIZE & STORE SELECTORS
- mov si,ax ; si = _SelCode selector
- mov ds:_SelCode,ax ;
-
- lea ecx,[eax+ebx] ; cx = _SelData selector
- mov ds:_SelData,cx ;
-
- lea ebp,[ecx+ebx] ; bp = _SelZero selector
- mov ds:_SelZero,bp ;
-
- mov ds:V86dx,offset em9_DPMImod
-
- ; WARNING! THIS CAN BE DANGEROUS!!! TRY ANOTHER METHOD!
- mov dx,cs
- lar dx,dx
- and dh,060h ; access rights AND RPL 3
-
- ; NOW LINK THE DESCRIPTORS TO THEIR SELECTOR INTO LDT
-
- mov ax,000ch ; COPY descriptors into DPMI LDT
- ; ax = 000ch
- ; bx = selector value
- ; ds:edi = pointer to the 8 bytes
- ; of data to COPY into
- ; the descriptor into GTD
-
- mov bx,si ;
- mov edi,offset ds:GDTcode32 ;
- or byte ptr [edi+5],dh ; cambia livello di protezione
- int 31h ;
- jc d16_exit16err ;
-
- mov bx,cx ;
- mov edi,offset ds:GDTdata32 ;
- or byte ptr [edi+5],dh ;
- int 31h ;
- jc d16_exit16err ;
-
- mov bx,bp ;
- mov edi,offset ds:GDTzero32 ;
- or byte ptr [edi+5],dh ;
- int 31h ;
- jc d16_exit16err ;
-
- ; SET EXTRA SEGMENT REGISTERS
- mov es,cx ;
- mov fs,cx ; ES,FS = Data32 (alias for Code32)
-
- mov gs,bp ; GS = linear addressing base
-
-
- ; CHECK IF THERE IS ENOUGH LOW MEMORY FOR PROGRAM DATA
- ; AND DMPI TABLES
- mov edi,ds:_LoMemBase
- mov eax,ds:_LoMemTop
- sub eax,edi
- cmp eax,128 ; minimum space needed for extended info
- mov ds:V86dx,offset em1_no_lomem
- jb d16_exit16err
-
- mov ds:_HiMemBase,0 ; better assume the worst
- mov ds:_HiMemTop ,0
-
- mov eax,(EXTMIN)
- or eax,eax
- jz rumblefish ; if no ext. mem required, go to set DPMI_state
-
- ; DPMI 00.90 ext. memory allocation
- ; initially my code checked for DPMI version numbers
- ; but found some inconsistent major release numbers
- ; so decided to support only the lowest common denominator (DPMI 0.9)
- mov ax,0500h ; ax = 0500 == GET DPMI INFO 0.9
- int 31h ; es:edi = info block (48 bytes wide)
-
- mov edx,es:[edi+08h] ; largest available lockable page number
- cmp edx,-1 ; (1page = 4K)
- je short DPMIdefault_alloc
- ; UNCOMMENT this code if you don't like the extra debug messages
- ; and think you can live with 128k less
- ;cmp edx,33
- ;jb short DPMIdefault_alloc
- ; sub edx,32 ; leave 128k free to system usage
- shl edx,12 ; allocate lockable pages
- jmp short DPMIbyte_alloc
- DPMIdefault_alloc:
- mov edx,(EXTMIN*1024) ; minimum space in Kbyte
- DPMIbyte_alloc:
- mov ds:V86dx,offset em3_no_himem
- cmp edx,(EXTMIN*1024)
- jb d16_exit16err
-
- or edx,edx ; zero bytes available ? go to next section
- rumblefish: ; rumblefish and ZERO FLAG from above !!!!!! :)
- jz short to_DPMI_state ; no need for extended memory
-
- ; ALLOCATE EXT. MEMORY THRU DPMI
- d16_winbumper:
- psay msg_DPMImem
- push edx
- mov cx,dx ; in:
- shld ebx,edx,16 ; ax = 0501
- mov ax,0501h ; bx:cx = ext. memory needed
- int 31h ; out:
- jnc d16_works ; CARRY CLEAR == NO ERRORS and ...
- mov ds:V86dx,offset em5_hifault ; bx:cx = linear address allocated
- ; si:di = memory block handle
- ; Aw! Something has gone wrong!
- pop edx
- cmp edx,(EXTMIN*1024)
- jbe d16_exit16err
- sub edx,4096 ; try one page less, and see if it works
-
- jmp d16_winbumper ; Usually Windows is to blame for this!
- to_DPMI_state:
- ; Don't touch this!!!!!!!!!
- jmp short DPMI_state
- d16_works:
- pop edx ; restore & save again requested memory
- push edx ;
- pushad ; try to lock all the memory you can get
- mov di,dx ; but don't care if you fail
- shld esi,edx,16 ; (i do this just to reduce disk swapping)
- mov ax,0600h ; if you wan to do serious irq handling into
- int 31h ; extende memory or want to DMA things
- popad ; you'd better relock the regions you use
- psay msg_DPMIwin
- pop edx
- shl ebx,16 ;
- mov bx,cx ; ebx = memory block linear address
- sub ebx,ds:_Code32Base ;
- mov ds:_HiMemBase,ebx ;
- add ebx,edx ;
- mov ds:_HiMemTop,ebx ; SET EXT MEM LIMITS
-
- DPMI_state:
- ; ALLOCATE DPMI_SAVE_TASK_STATE BUFFERS AND POINTERS
-
- mov ax,0305h ; get save/restore state addresses
- int 31h ;
-
- mov ds:d32_StateBufferSize,ax ; leght of save state block
-
- ; 32bit save/restore state protected-mode routine
- mov dword ptr ds:d32_SaveRestoreState[0],edi ; offset32
- mov word ptr ds:d32_SaveRestoreState[4],si ; seg32
-
- ; 16 bit save/restore state real-mode routine
- mov word ptr d16_SaveRestoreState[0],cx ; offset16
- mov word ptr d16_SaveRestoreState[2],bx ; seg16
-
- ; SET MODE SWITCH CODE POINTERS
-
- mov ax,0306h ; get raw Mode Switch to 16<-->32 bit mode
- int 31h ;
-
- ; switch protected->real mode routine
- mov dword ptr ds:d32_Fast32_To_16[0],edi ; offset 32
- mov word ptr ds:d32_Fast32_To_16[4],si ; seg32
-
- ; switch real->protected mode routine
- mov word ptr d16_Fast16_To_32[0],cx ; offset16
- mov word ptr d16_Fast16_To_32[2],bx ; seg16
-
- ; NOW SET IRQs & INTs
-
- ; set IRQ handlers to PIC values
- mov ax,0400h ; Get DPMI version info
- int 31h ; dh = 1st PIC base vector dl= 2nd PIC base vector
-
- mov di,offset ds:intslotnum ;
- xchg dl,dh ;
- mov bx,dx ;
- call setintslots ; set new vector table for IRQ
- psay msg_DPMIirq
- mov ah,02 ; backup and set all int vectors
- mov si,ds:_SelCode ;
- mov edi,17 ;
-
- DPMI_SavSetInts:
- mov bl,ds:intslotnum[di] ;
- mov al,04 ; ah was 02, so execute function 0204h
- int 31h ; GET INT VECTOR bl
-
- lea ebp,[edi*2+edi]
- mov dword ptr ds:d32_OldInts[ebp*2],edx
- mov word ptr ds:d32_OldInts[ebp*2+4],cx
-
- mov al,05 ;
- movzx edx,d16_nintoff[edi*2] ; ah was 02, so execute function 0205h
- mov cx,si ; SET INT VECTOR bl
- int 31h ;
-
- sub di,1
- jnc DPMI_SavSetInts
-
- ; DPMI GOES TO 32bit INIT STUFF
- push es ; set up needed regs & go on to 32bit!
- pop ss
- add esp,ds:StackBaseAddress
- jmp JoinDPMI
-
- ;-----------------------------------------------------------------------------
- ; 16bit VCPI system code
-
- v16_retreal: ; VCPI return to real mode ( called from _Exit routine)
- ; conversione ESP da 32bit a 16bit, risultato in EBX
- mov ebx,esp
- sub ebx,ds:StackBaseAddress ;ritorna all' offset valido in modo reale
-
- mov eax,code16
- mov ecx,codeend
-
- ; now set-up the return environment
- ; (n.b. 16bit values MUST be pushed as dwords)
- push eax ; DWORD GS = code16
- push eax ; DWORD FS = code16
- push eax ; DWORD DS = code16
- push eax ; DWORD ES = code16
- push ecx ; DWORD SS = codeend
- push ebx ; DWORD ESP = translated offset
- pushfd ; DWORD EFLAGS
- push eax ; DWORD CS = code 16
- dw 6866h,v16_retreal2,0 ; 32bit PUSH offset v16_retreal2
- mov ax,gs ;
- mov ds,ax ; load linear memory descriptor into DS
- mov ax,0de0ch
- call cs:v32_vcpientryaddr ; N.B. this is a FAR call
-
- ;-----------------------------------------------------------------------------
- ; VCPI REAL MODE INT32: EDX=off
- VCPI_Int32_From_Real_Mode:
- mov eax,offset v32_call386P
- ; join VCPI_SWITCH
-
- ;------------------------------------------------------------------------------
- ; CALL TO 16bit prot mode : EAX=offset to jump to in code32
-
- VCPI_SWITCH: ; VCPI switch to protected mode from v86 mode
- ; or from v86 mode to protected mode
- ; (here we use the VCPI_SWITCH to go to protected mode)
- mov cs:v16_sw_dest,eax ; offset to jump at
- mov esi,cs:v16_VCPIsys ; system data for mode switch
-
- mov ax,0de0ch ; SWITCH TO 16bit PROTECTED MODE thru VCPI
- int 67h ;
-
- v16_retreal2:
- ; just returned to real mode from protected mode
- cli
- ; if something fails, you get here ..
- VCPI_exit: ; VCPI exit (clean up paging stuff)
- mov es,v16_PageDirSeg
- mov si,v16_PageBase
- mov cx,v16_PageTop
-
- sub cx,si ; Need to deallocate VCPI memory pages ?
-
- jz short page_cleaned ; No! Only remove EMS data
- ; Yes! Clean pages
- say msg_VCPIfree
- VCPI_clean: ; Deallocate memory pages allocated thru VCPI
-
- mov edx,es:[si] ;
- and dx,0f000h ; edx == address of 4k page to deallocate & unlink
-
- mov ax,0de05h ; call page unlink function
- int 67h ;
-
- add si,4 ; next page
-
- sub cx,4 ; loop if there are other pages to clean
- jnz VCPI_clean ;
- page_cleaned: ; now go to standard exit code
- jmp exit
-
- VCPI_err1: ; VCPI not enough low mem exit
- mov dx,offset em1_no_lomem
- jmp exit16err
-
- ;=============================================================================
-
- StartVCPI: ; Init VCPI
- or ds:_386Man,IS_VCPI ; set system type = VCPI
-
- mov eax, ds:v16_VCPIsys ; adjust linear pointer
- add eax, ds:_Code16Base ; to switch parameters
- mov ds:v16_VCPIsys,eax ;
-
- mov exitrout,offset exit ; set standard dos-cleanup exit
-
- ; NOW HANDLE PICs YOURSELF
- mov ax,0de0ah ; get PIC base vector mappings
- int 67h ; BX,CX = first vector of master PIC and slave PIC
- mov bh,cl ; bh= now is first vector of slave PIC
- ; N.B. A single PIC uses 8 consecutive vector numbers
- ; so you'd better avoid to use the vector base 030h
- ; or your interrupts will "cover" then int 31h, int32h, int 33h
- ; 386power interface
- mov s16_OldPICInt,bx ; save PIC base vector mappings
-
- mov dx,offset em11_EqPIC ; set error message if something goes wrong
-
- ; Check for compatible PIC mapping ...
- cmp bl,bh
- je exit16err ; Uh? Mapped as equal ? Whats that? Are you crazy ?
- ; I'm NOT a fucking old IBM XT
-
- mov dx,offset em6_PICfault ; set error message if something goes wrong
- cmp bl,30h
- je exit16err ; Low mapping clashes with service ints
- cmp bh,30h
- je exit16err ; High mapping clashes with service ints
-
- ; SET UP NEW P.I.C. MAPPINGS
- mov ax,70h ; new mapping = highest_needed_int - 7
- ; infatti si ha 2ch+7 = 33h
- cmp al,bl ;
- ja short HIPIC1 ; max int mapping > master pic mapping ?
- mov al,bl ;
- HIPIC1: ;
-
- cmp al,bh ; max int mapping > slave pic mapping ?
- ja short HIPIC2 ;
- mov al,bh ;
- HIPIC2: ;
-
- add al,7 ; add the 7 exceptions handlers
- ; to get the IDT SIZE
-
-
- mov s16_Int_to_replace_ctr,al ;
-
- ; SET INT VECTOR TABLE
- lea eax,[eax*8+7] ; set limit of IDT
- mov s16_IDT32addr,ax ; (don't, worry we use the lower 16 bits)
- ; bl,bh == int slots for master & slave PIC
- mov di,offset ds:intslotnum ; set int slots as needed
- call setintslots ;
-
- ; NOW ALLOCATE&INITIALIZE TSS AND IDT
- VCPI_IDT_TSS:
- ; ALLOCATE SPACE FOR TSS AND IDT
- movzx eax,s16_IDT32addr ; get (limit -1) of IDT
- add eax,(2068h+1) ; TSS is 68h bytes wide
- ; and we need extra space
- ; for IO bitmap
- call InitAlloc ; allocate space for TSS and IDT
-
- mov ds:s32_tssesp0ptr,eax ; registra TSS base address
-
- ; eax = base of allocated block
-
- ; questa roba la faceva la prima versione di pmode 386
- mov ebp,ds:_Code32Base ; set Task Switch Selector address
- lea ebx,[eax+ebp] ; into GTD
- or dword ptr ds:GDTtask[2],ebx ;
-
- add ebx,2068h ; set IDT base address
- mov dword ptr ds:s16_IDT32addr[2],ebx ;
-
- mov eax,ds:_Code16Base ; convert GTD & IDT addresses
- add dword ptr v16_sw_gdtaddrptr,eax ; from code16-relative offsets
- add dword ptr v16_sw_idtaddrptr,eax ; to LINEAR addresses
-
- mov exitrout,offset VCPI_exit ; set VCPI error&exit routine
-
- mov eax,ds:_LoMemBase ; align lomem base on a 4k page
- mov ebx,ds:_Code32Base ;
- add ebx,eax ;
- lea ecx,[ebx+0fffh] ;
- and ecx,0fffff000h ; ecx == _LoMemBase as LINEAR address
- sub ebx,ecx ;
- sub eax,ebx ;
- mov ds:_LoMemBase,eax ; eax == _LoMemBase as OFFSET from code32
-
- mov ebp,ds:_LoMemTop ; get available low memory
- sub ebp,eax ;
- sub ebp,LOWMIN*1024 ; die if not enough low memory
- jc VCPI_err1 ;
- cmp ebp,8192 ; die if no space for minimal page structure
- jb VCPI_err1 ;
-
- shr ecx,4 ; set VCPI 386POWER page-directory segment
- mov v16_PageDirSeg,cx ;
- ; The 8k allocated in low memory are split into
- ; 1) a 4K (1000h) PAGE DIRECTORY
- ; 2) a 4k PAGE TABLE (the first page table, others are chained to it)
-
- mov es,cx ; reset all addresses
- xor di,di ;
- mov cx,2048 ;
- xor eax,eax ;
- rep stos dword ptr es:[di] ;
-
- ; GET VCPI 32BIT INTERFACE
- mov di,1000h ; es:di == pointer to FIRST PAGE TABLE
- ; (vcpi inits it with the pages already allocated)
-
- mov si,offset ds:GDTvcpi ; Get Vcpi Protected Mode Interface
- mov ax,0de01h ; in: ax = 0de01h
- int 67h ; es:di = ptr to 4k page table buffer
- ; ds:si = ptr to 3 descriptor table entries
- ; the first becomes the
- ; code segment descriptor
- ; the other two are used by
- ; the MAIN CONTROL PROGRAM
- ; out: ebx = offset of prot. mode entry point
- ; (relative to GDTvcpi)
- ; es:di = first unused page table entry
- ; in page table buffer
-
- mov dword ptr ds:v32_vcpientryaddr,ebx
-
- ; DI = end of allocated entries on page table
- ; ONE ENTRY takes 4 bytes, one entry is a 4k page
- ; so if you subtract the page base offset (1000h)
- ; DI is EXACTLY how many Kbytes has been allocated by VCPI
- ; starting from "your task" linear address 00000000h
-
- mov v16_PageBase,di ; set up and go through page map allocation
- mov v16_PageTop,di ;
-
- movzx eax,di ;
- sub eax,1000h ;
- shl eax,10 ; eax = base of extended memory in bytes
-
- mov ebp,ds:_Code32Base ;
-
- sub eax,ebp ;
- mov ds:_HiMemBase,eax ; STORE INITIAL _HiMemBase
-
- ; NOW SET EBX AS A COUNTER OF THE BYTES ALLOCATED
- ; IN LOW MEMORY FOR PAGING INFO
- mov ebx,8192 ; one page directory + one page table
-
- page_table_alloc:
- mov ax,0de04h ; Allocate one page, ax =0de04h
- int 67h ; out: ah = error code ( 00 == no errors)
- or ah,ah ; edx = linear address of allocated page
- jnz short end_page_alloc
-
- test di,0fffh ; Check if at end of page table
- jnz short not_4k_boundary ;
-
- add ebx,4096 ; add space for another 4k page table
- cmp ebx,ds:_LoMemTop ; run out of low memory ?
- ja VCPI_err1 ;
-
- not_4k_boundary:
- and dx,0f000h ; Mark this page as one-page-block
- or dl,7 ; (but movable if needed)
- mov es:[di],edx ; store entry on page table
- add di,4 ;
- jns page_table_alloc ; STOP if allocated 32Mbytes of ext. mem.
-
- end_page_alloc:
- mov v16_PageTop,di ; Store final allocated page table limit
-
- lea si,[di-1000h] ;
- movzx eax,si ;
- shl eax,10 ; eax = LINEAR address of allocated ext. mem. limit
-
- sub eax,ebp ; EBP is still_Code32Base
- mov ds:_HiMemTop,eax ; store _HiMemTop
-
- sub di,v16_PageBase ;
- cmp di,EXTMIN ;
-
- mov dx,offset em3_no_himem
- jb exit16err
-
- add ds:_LoMemBase,ebx ;
-
- ; QUELLO CHE SEGUE ERA ASSAI SOSPETTO !!!!!
- ; HO DOVUTO CODIFICARE TUTTO "A NASO" confidando
- ; che i progettisti di VCPI non siano delle teste a pera.
-
- movzx eax,v16_PageDirSeg ;
- shl eax,4 ; page_dir segment as linear address
-
- mov ebx,1000h ; PAGE SIZE
-
- mov v16_sw_cr3,eax ; SET PAGE REGISTER
-
- ; NOW IT'S TIME TO INITIALIZE THE PAGE DIRECTORY
- ;
- xor di,di ; es:di == page directory address
- set_page_directory:
- add eax,ebx ; prossima page table
- and ax,0f000h ; Why this ? A MISTERY to me!
- or al,7 ; Looks like we have to set paging info stored
- stosd ; into page table location on page dir. entry
- sub si,bx ; 4Mbytes has been mapped in a single page dir entry
- ja set_page_directory
-
- ; NOW PATCH DOS EXTENDED CODE FOR VCPI
- mov ebx,ds:s32_tssesp0ptr
- mov eax,offset VCPI_protected16 ; offset to jump to in 386P
- jmp VCPI_SWITCH ; BANG! HERE WE GO PROTECTED
-
- VCPI_protected16: ; in 16bit prot. mode
- ; Now set 32 bit protected mode segments and stack pointer
- ; for VCPI
- ; (DPMI uses the selectors allocated from the DPMI server)
-
- mov ax,28h ;
- mov ds,ax ; ds= data16
-
- mov al,18h ;
- mov gs,ax ; gs= linear
-
- mov al,10h ; es,fs,ss = data32
- mov es,ax ;
- mov fs,ax ;
- mov ss,ax ;
-
- mov esp,STACKSIZE*16 ; stack size
-
- add esp,ds:StackBaseAddress ; esp = prot. mode stack base
- ; now in 32bit mode
- VCPI_set_TSS_data:
- ; ebx = address of TSS ( code32 relative )
- ; new FROM PMODE24
-
- ; First switch was from code16 to code16
- ; next switches will be from code16 to code32
-
- lea eax,[ebx+4] ; eax = address of ESP0 in TSS
- mov ds:s32_tssesp0ptr,eax ; store pointer to ESP0
- ; (needed for VCPI task switchers)
- mov es:[eax],esp
-
- ; remember: ds== data16 es==data32
-
- ; set up TSS stuff (EBX == TSS base)
-
- ; dword ptr, come mai ????
- mov dword ptr es:[ebx+8],10h ; set SS of CPL0
-
- mov edi,104 ; 104 == 68h == fine del TSS
- mov es:[ebx+102],di
- mov word ptr es:[ebx+100],0
-
- add edi,ebx ; Fill IO bitmap with 0
- xor eax,eax ; If it works for Tran, it works for me too!
- mov ecx,800h ; (i've already tried without this)
- rep stosd ;
-
- ; non mi sembra che fare una cosa del genere sia salutare
- ;mov cx,30h
- ;ltr cx
-
- ; riprende il vecchio codice
-
- VCPI_ready32:
- ; First switch was from code16 to code16
- ; next switches will be from code16 to code32
- mov word ptr v16_sw_dest[4],8
-
- mov ecx,offset s16_idt32handler ; int handler table
-
- mov edi,dword ptr s16_IDT32addr[2]; get ptr to IDT
- sub edi,ds:_Code32Base ; get
-
- ; Common code for final initialization
-
- ; now inizialize IDT with general exception handler
-
- mov ds:s32_idt32ptr,edi
- ; now EDI == base pointer to IDT32
- ; ECX == base pointer to IDT16
-
- ; set general excpection handlers
- movzx esi,s16_Int_to_replace_ctr
-
- mov eax,offset s32_excf ;
- and eax,0000ffffh ; parte bassa offset s32_excf
- add eax,00080000h ; selettore codice
-
- mov ebp,00008E00h ; flags & parte alta offset azzerata
- ; (tanto il nucleo e' al di sotto dei 64k)
- ; e' uno sporco trucco ... ma mi piace!
-
- ; Struttura di una IDT entry (8 bytes)
- ; offset size
- ; 0 2 parte bassa offset ISR (Interrupt Service Routine)
- ; 2 2 selettore segmento ISR
- ; 4 2 flags vari
- ; 6 2 parte alta offset ISR
-
- SetIDTEntry:
- ; selettore = 8
- ; offset = offset s32_excf (handler generalizzato)
- mov dword ptr es:[edi+esi*8],eax ; offset basso e selettore
- mov dword ptr es:[edi+esi*8+4],ebp ; flags & offset alto azzerato
- dec si ; WARN
- jns SetIDTEntry
-
- ; copy exception handlers from IDT
- mov esi,33
- SetIDTInt:
- movzx ebp,byte ptr ds:intslotnum[si]
- mov ax,[ecx+esi*2] ; prendi l' offset dell' ISR da s16_idt32handler
- mov es:[edi+ebp*8],ax ; scrivilo
- dec si ; WARN
- jns SetIDTInt
-
- ; HERE WE GO TO 32bit PROTECTED MODE
- pushfd ; set eflags: NT=0, IOPL=3
- pop eax
- and ah,0bfh
- or ah,30h
- push eax
- popfd
-
- ; READY TO ENTER 32BIT PROTECTED MODE
-
- JoinDPMI: ; shared by VCPI & DPMI
- ; NOW WE CAN ENTER 32BIT PROTECTED MODE
- push es
- pop ds
- push dword ptr cs:_SelCode ;
- push offset INIT_386P ;
- db 66h,0cbh ; 32bit RETF go to 32bit stuff
-
- ; =========================
- ; NATIVE 16 bit system code
- ; =========================
-
- s16_irqreal: ; native 386 real mode IRQ from 32bit prot. mode
- pushf
- push cs
- push offset IREAL_TERMINATOR
- mov eax,cs:tempaddr
- jmp cs:[eax*4+_OldInt]
-
- code16 ends
-
- ; 32bit code
- code32 segment para public use32
- assume cs:code32, ds:code32
- org 0
-
- extrn _Main:near
-
- public _Exit, _GetMem, _GetLoMem, _GetHiMem
- public _GetIRQMask, _SetIRQMask
-
- public V86eax, V86ebx, V86ecx, V86edx, V86esi, V86edi, V86ebp
- public V86ax, V86bx, V86cx, V86dx, V86si, V86di, V86bp
- public V86al, V86ah, V86bl, V86bh, V86cl, V86ch, V86dl, V86dh
- public V86ds, V86es, V86fs, V86gs
- public _SelCode, _SelData, _SelZero, _LoMemBase, _LoMemTop, _HiMemBase
- public _HiMemTop, _PSPBase, _Code16Base, _Code32Base, _GetIRQ, _SetIRQ
- public _386Man
-
- ; 32 bit common system data
-
- dd ? ; scratch dword for VCPI tss esp0
- align dword
- _LoMemBase dd 0 ; low mem base for allocation
- _LoMemTop dd 0 ; top of low mem
-
- _HiMemBase dd 0 ; high mem base for allocation
- _HiMemTop dd 0 ; top of high mem
-
- _PSPBase dd ? ; LINEAR offset of start of PSP
- _Code16Base dd ? ; LINEAR offset of start of 16bit code
- _Code32Base dd ? ; LINEAR offset of start of 32bit code
-
- _GetIRQ dd s32_getirq ; get IRQ handler offset routine addr
- _SetIRQ dd s32_setirq ; set IRQ handler offset routine addr
-
- align word
- _SelCode dw 8 ; code segment selector
- _SelData dw 10h ; data segment alias for code
- _SelZero dw 18h ; data segment starting at 0:0
-
-
- align byte
- ; Global Descriptors Table
- GDT dq 0 ; selettore 00h
- GDTcode32 db 0ffh,0ffh,0,0,0,9ah,0cfh,0 ; 08h
- GDTdata32 db 0ffh,0ffh,0,0,0,92h,0cfh,0 ; 10h
- GDTzero32 db 0ffh,0ffh,0,0,0,92h,0cfh,0 ; 18h
- GDTcode16 db 0ffh,0ffh,0,0,0,9ah,0,0 ; 20h
- GDTdata16 db 0ffh,0ffh,0,0,0,92h,0,0 ; 28h
- GDTtask db 0ffh,0ffh,0,0,0,89h,0,0 ; 30h
- GDTvcpi dq 3 dup(?) ; 38h,40h,48h
- ; il selettore 38h e' quello della GDT
- ; il selettore 40h e' un data segment sulla pagina zero
- ; il selettore 48h e' un segmento dati a 32bit
-
- ; Virtual 8086 Registers
- V86edi label dword ; vregs for 386P<-->V86 communication
- V86di dw 0, 0 ; we need this order if we want
- V86esi label dword ; to bypass 386POWER and go thru DPMI API
- V86si dw 0, 0 ;
- V86ebp label dword ; I'm planning to support more than
- V86bp dw 0, 0 ; DPMI 900h 901h & 902h
- dd 0 ; if DPMI becomes prevalent.
- V86ebx label dword
- V86bx label word
- V86bl db 0
- V86bh db 0, 0,0
- V86edx label dword
- V86dx label word
- V86dl db 0
- V86dh db 0, 0,0
- V86ecx label dword
- V86cx label word
- V86cl db 0
- V86ch db 0, 0,0
- V86eax label dword
- V86ax label word
- V86al db 0
- V86ah db 0, 0,0
- V86F dw 0
- V86es dw 0
- V86ds dw 0
- V86fs dw 0
- V86gs dw 0
- dd 0,0
-
- OldBreakISR dd ? ; old int 1Bh (ctrl+break)
- OldIRQMask dw ? ; old port 21h and 0a1h masks
-
- align byte
-
- _386Man db 0 ; system bits:
- ; bit 1: 0=VCPI, 1=DPMI
-
- intslotnum db 16 dup(0)
- ; 16 int vectors for the two PICs
- db 33h,32h,31h,0,1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh
- ; these are the 386power API & exception handlers vectors
- align word
-
- _EXIT_OFS dw v16_retreal ; offset in 16bit of exit function
- _EXIT_SEL dw 20h ; 16bit 386P code selector
- _EXIT_DATA_SEL dw 28h ; 16bit 386P data selector
-
- nextmodestack dw (STACKSIZE-STACKSLOT)*16 ; stack for next mode switch
-
- align dword
- tempaddr dd ? ; temporary address, seg:off or off
- StackBaseAddress dd ? ; linear ptr to beginning of codeend
-
- d32_Fast32_To_16 df ? ; switch from 32 to 16
- d32_SaveRestoreState df ? ; save/restore state addr
- d32_StateBufferSize dw 0,0 ; length of state buffer
- d32_SavStackOfs dd ? ; current saved stack offset
- d32_SavStackSel dw ? ; current saved stack selector
-
- d32_OldInts df 18 dup(?) ; saved interrupt addr buffer
-
- ;----------------------------------------------------------------------------
- ; 32 bit VCPI system data
-
- v32_vcpientryaddr df 3800000000h ; VCPI entry point in 386P
-
- ;----------------------------------------------------------------------------
- ; 32 bit custom system data
-
- align dword
- s32_tssesp0ptr dd 0 ; ptr to ESP0 in TSS, or null in VCPI
- s32_idt32ptr dd 0 ; ptr to 32bit IDT
-
- s32_irq_num dd 0 ; int num of IRQ for V86 mode
- s32_SavStackOfs dd 0 ; current saved stack offset
-
- DV_INT32INTFLAG dd 0 ; interrupt flag for VCPI/DPMI int 32h
- align byte
- ;---------------------------------------------------------------------------
- ; 32 bit common system code
- ;---------------------------------------------------------------------------
-
- INIT_386P: ; common 32bit startup
-
- ; disable ctrl+break
- mov eax,gs:[1bh*4] ; SAVE ctrl+break value, then crtl+break OFF
- mov OldBreakISR,eax ;
- db 65h,67h,0c7h,6 ; MOV DWORD PTR GS:[1bh*4],code16:nullint
- dw 1bh*4,nullint,code16 ;
-
- in al,21h ; save old PIC masks
- mov ah,al ;
- in al,0a1h ;
- mov OldIRQMask,ax ;
-
- jmp _Main ; go to main code
-
- ; 386POWER API routines (fully compatible with PMODE API)
-
- ; Allocate any mem, (first try low, then high)
- ; In:
- ; EAX = size requested
- ; Out:
- ; CF CLEAR = memory allocated
- ; CF SET = not enough mem
- ; EAX = linear pointer to mem or ?
- _GetMem:
- push eax
- call _GetLoMem
- jnc short getmemd
- pop eax
- jmp short _GetHiMem
- getmemd:
- add esp,4
- ret
-
- ; Allocate some low mem
- ; In:
- ; EAX = size requested
- ; Out:
- ; CF CLEAR = memory allocated
- ; CF SET = not enough mem
- ; EAX = linear pointer to mem or ?
- _GetLoMem:
- add eax,_LoMemBase
- cmp eax,_LoMemTop
- ja short getmemerr
- xchg eax,_LoMemBase
- clc
- ret
- getmemerr:
- stc
- ret
-
- ; Allocate some high mem
- ; In:
- ; EAX = size requested
- ; Out:
- ; CF CLEAR = memory allocated
- ; CF SET = not enough mem
- ; EAX = linear pointer to mem or ?
- _GetHiMem:
- add eax,_HiMemBase
- cmp eax,_HiMemTop
- ja short getmemerr
- xchg eax,_HiMemBase
- clc
- ret
-
- ; Get status of IRQ mask bit
- ; In:
- ; BL = IRQ num (0-15)
- ; Out:
- ; AL = status: 0=enabled, 1=disabled
- _GetIRQMask:
- push ax
- in al,0a1h ; get IRQ mask
- mov ah,al ;
- in al,21h ;
- xchg cl,bl ;
- shr ax,cl ; shift bit to bit0
- xchg cl,bl
- and al,1 ; mask out other bits
- pop ax
- ret
-
- ; Set status of IRQ mask bit
- ; In:
- ; BL = IRQ num (0-15)
- ; AL = status: 0=enabled, 1=disabled
- _SetIRQMask:
- push ax bx cx dx
- mov cl,bl
- mov bx,0fffeh
- movzx dx,al
- rol bx,cl
- shl dx,cl
- in al,0a1h
- mov ah,al
- in al,21h
- and ax,bx
- or ax,dx
- out 21h,al
- mov al,ah
- out 0a1h,al
- pop dx cx bx ax
- ret
-
- ;------------------------------------------------------------------------------
- ; Exit to real mode
-
- _Exit: ; 32bit side of shutdown code
- cli ; interrupts off
- ; set default timer interval into PIT0
- mov ax,36h ; PIT channel 0, square wave,binary, send LSB & MSB
- out 43h,al ; send command
- mov al,0
- out 40h,al ; maximum timer count (freq. = 18.2 Hz)
- out 40h,al ;
- mov ax,0B6h ; PIT channel 2, square wave,binary, send LSB & MSB
- out 43h,al ; send command
- mov al,0
- out 42h,al ; maximum timer count (freq. = 18.2 Hz)
- out 42h,al ;
- sti
- mov V86ax,0003 ; restore text mode 80x25
- mov al,10h ;
- int 33h ;
- cli
- in al,61h ; disable sound
- and al,011111100b ;
- out 61h,al ;
- mov eax,OldBreakISR ; restore ctrl+break
- mov gs:[1bh*4],eax
- mov ax,OldIRQMask ; restore PIC masks
- out 0a1h,al
- jc delay1 ; delay a little
- delay1: jnc delay2 ;
- delay2: ;
- mov al,ah
- out 21h,al
- push _EXIT_SEL ; go to 16bit 386P exit code
- push _EXIT_OFS
- mov ds,_EXIT_DATA_SEL
- db 66h,0cbh ; 16bit RETF
-
- ;------------------------------------------------------------------------------
- ; 32 bit DPMI system code
- ;------------------------------------------------------------------------------
- v32_call386P: ; VCPI 386P call from real mode
- mov esp,ebx ; set new stack slot
- mov ax,10h
- mov ds,ax
- mov es,ax
- mov ss,ax
- ; now share code with DPMI
- d32_call386P: ; DPMI 386P call from real mode
- cld
- ; DS,CS,ES set by DPMI server OR by VCPI custom code
- mov ax,ds
- mov fs,ax
- mov gs,_SelZero
- ; ONLY SEGMENT REGISTERS, STACK POINTER AND Direction Flag
- ; ARE SET TO RESPECT 386Power ENVIRONMENT
- ; This is not like the Int 32h callable in protected mode !!!!
- push offset d32_call386Pdone
- push tempaddr
- cmp ds:DV_INT32INTFLAG,0
- jne d32_call_with_sti
- cli
- ret ; now call near routine in code32
- d32_call_with_sti:
- sti
- ret ; as above, but with ints enabled
-
- d32_call386Pdone:
- cli
- ; registers are trashed to gain speed on callback termination
- ; THIS IS NOT LIKE THE INT 32h IN PROTECTED MODE
- mov ecx,_Code16Base
- movzx ebx,gs:d16_SavStackOfs[ecx]
- movzx edx,gs:d16_SavStackSeg[ecx]
- mov eax,code16
-
- cmp cs:_386Man,IS_VCPI ;
- je v32_call386Pdone ; redirect if IS_VCPI
- ; DPMI return to real mode
- mov cx,dx
- mov si,ax
- mov edi,offset DPMI_Return_Int32R
- jmp d32_Fast32_To_16
-
- v32_call386Pdone: ; VCPI done with 386P call
- push eax
- push eax
- push eax
- push eax
- push edx
- push ebx
- pushfd
- push eax
- db 68h ; 32bit PUSH offset DONE_INT32R_DPMI_VCPI
- dw DONE_INT32R_DPMI_VCPI,0 ;
- mov ax,gs
- mov ds,ax
- mov ax,0de0ch
- call cs:v32_vcpientryaddr ; n.b. this is a FAR call
-
- ;------------------------------------------------------------------------------
- d32_int32: ; DPMI INT 32h: CX:DX=seg:off
- pushad
-
- shl ecx,16 ; store seg:ofs into ECX
- mov cx,dx ;
-
- mov bp,offset callreal ; redirect to CALL REAL MODE ROUTINE
-
- ; now join common int code
- jmp short d32_16common
-
- d32_int33: ; DPMI INT 33h: AL=int num
- pushad
- ; AND HERE WE GO TO VIRTUAL 8086 MODE
- ; PUTTING INTO tempaddr the offset of the interrupt vector to call
- ; from the _OldInt vector table
- movzx ecx,al ;get vector offset int _OldInt
-
- mov bp,offset intreal ; redirect to INT REAL MODE ROUTINE
-
- ; join common int code
-
- d32_16common: ; int or call to real mode
- mov ax,0900h ; DPMI get state of Interrupt Flag and DISABLE IT
- int 31h
- ; AL = Interrupt Flag status
-
- mov tempaddr,ecx ; address to jump at in seg:ofs format
-
- push ax ; save Int Flag status
-
- push d32_SavStackOfs ; save current SAVED stack
- push d32_SavStackSel ;
-
- movzx ebx,nextmodestack ; allocate a new stack frame
- lea eax,[ebx-STACKSLOT*16] ;
- mov nextmodestack,ax ;
-
- mov ax,ss ;
- mov es,ax ; ES == save state segment
-
- sub esp,dword ptr d32_StateBufferSize ; allocate DPMI save state buffer
- mov edi,esp ;
-
- ; es:edi = pointer to save state buffer
- xor al,al ; AL=0 -> SAVE TASK STATE INFO
- call d32_SaveRestoreState ; save DPMI info about this stack
-
- mov d32_SavStackOfs,esp ; save stack
- mov d32_SavStackSel,ss ;
-
- mov cx,V86es ; real mode ES
- mov dx,codeend ; real mode SS
- mov ax,V86ds ; real mode DS
-
- movzx edi,bp ; real mode EIP
- mov si,code16 ; real mode CS
- jmp d32_Fast32_To_16
-
- ; DPMI RETURN FROM V86
- d32_16done:
- mov edi,esp ; current stack pos
- ; ES:EDI == pointer to save state buffer
- mov al,1 ; AL=1 -> RESTORE TASK STATE INFO
- call d32_SaveRestoreState ; get last DPMI info saved
-
- add esp,dword ptr d32_StateBufferSize ; remove DPMI INFO block
-
- pop d32_SavStackSel ; Restore previous saved stack
- pop d32_SavStackOfs ;
-
- add nextmodestack,STACKSLOT*16 ; restore space used for previous
- ; stack frame
-
- mov bx,V86F ;
- mov ax,[esp+42] ;
- and ax,not 8d5h ;
- and bx,8d5h ;
- or ax,bx ;
- mov [esp+42],ax ; write user flags on register image on stack
-
- pop ax ; RESTORE Int Flag found on entry to mode-switch routine
- mov ah,9 ;
- int 31h ; restore previous Int Flag status
-
- mov ax,ds ; restore selectors
- mov es,ax ;
- mov fs,ax ;
- mov gs,_SelZero ;
-
- popad ; restore registers
- iretd
-
- ;------------------------------------------------------------------------------
- ; DPMI IRQ redirectors (needed to make all IRQ vector selectors = CS)
-
- d32_irq0:
- jmp cs:d32_OldInts[0]
- d32_irq1:
- jmp cs:d32_OldInts[6]
- d32_irq2:
- jmp cs:d32_OldInts[12]
- d32_irq3:
- jmp cs:d32_OldInts[18]
- d32_irq4:
- jmp cs:d32_OldInts[24]
- d32_irq5:
- jmp cs:d32_OldInts[30]
- d32_irq6:
- jmp cs:d32_OldInts[36]
- d32_irq7:
- jmp cs:d32_OldInts[42]
- d32_irq8:
- jmp cs:d32_OldInts[48]
- d32_irq9:
- jmp cs:d32_OldInts[54]
- d32_irqa:
- jmp cs:d32_OldInts[60]
- d32_irqb:
- jmp cs:d32_OldInts[66]
- d32_irqc:
- jmp cs:d32_OldInts[72]
- d32_irqd:
- jmp cs:d32_OldInts[78]
- d32_irqe:
- jmp cs:d32_OldInts[84]
- d32_irqf:
- jmp cs:d32_OldInts[90]
-
- ;------------------------------------------------------------------------------
- ; DPMI IRQ REDIRECTORS
- ;------------------------------------------------------------------------------
-
- ; DPMI get IRQ handler offset
- ; In:
- ; BL - IRQ num (0-0fh)
- ; Out:
- ; EDX - offset of IRQ handler
-
- d32_getirq:
- pushad
- mov ax,0204h
- movzx bx,bl
- mov bl,intslotnum[bx]
- int 31h
- popad
- ret
-
- ; DPMI set IRQ handler offset
- ; In:
- ; BL - IRQ num (0-0fh)
- ; EDX - offset of IRQ handler
-
- d32_setirq:
- pushad
- mov ax,0205h
- movzx bx,bl
- mov bl,intslotnum[bx]
- mov cx,cs
- int 31h
- popad
- ret
-
- ;-----------------------------------------------------------------------------
- ; VCPI STUFF
- ;-----------------------------------------------------------------------------
-
- ;-----------------------------------------------------------------------------
- ; 32 bit custom system code
- ;-----------------------------------------------------------------------------
- s32_int31: ; INT 31h: AX=900h,901h,902h
- cmp al,1
- mov al,[esp+9]
- jb short s32_int31f0
- ja short s32_int31f1
- or byte ptr [esp+9],2
- jmp short s32_int31f1
- s32_int31f0:
- and byte ptr [esp+9],0fdh
- s32_int31f1:
- shr al,1
- and al,1
- iretd
-
- ; 386POWER API ints
- s32_int32: ; INT 32h: CX:DX=seg:off
- pushad
- shl ecx,16
- mov cx,dx
- mov ebp,offset callreal
- jmp short s32_16common
-
- s32_int33: ; INT 33h: AL=int num
- pushad
- movzx ecx,al
- mov ebp,offset intreal
-
- s32_16common: ; int or call to real mode
- mov tempaddr,ecx
-
- mov edi,[esp+40] ; EXCTRACT FLAG INFO & PUT IT ON EDI
- shld eax,edi,23 ;
-
- movzx esi,nextmodestack ; new stack frame
- lea eax,[esi-STACKSLOT*16] ;
- mov nextmodestack,ax ; eax = new stack offset
-
- mov ebx,s32_tssesp0ptr ;
- push dword ptr [ebx] ; salva ESP0 relativo a data32
-
- add eax,StackBaseAddress ; eax = new linear stack pointer data16
- mov [ebx],eax ; STORE new stack on TSS esp0
-
- push s32_SavStackOfs ;
- mov s32_SavStackOfs,esp ; save stack
-
- xor eax,eax ;
- push eax ;
- push eax ; 2 null dwords
-
- mov ax,V86ds ; DS
- push eax ;
-
- mov ax,V86es ; ES
- push eax ;
-
- mov ax,codeend ; SS
- push eax ;
-
- push esi ; ESP
-
- or edi,20000h ;
- and di,0fdffh ;
- push edi ; store protected flags
-
- db 68h ; 32bit PUSH code16
- dd code16 ;
- push ebp ; epb = intreal xor callreal
-
- mov ax,0018h ; VCPI switch to real mode routine
- mov ds,ax
- mov ax,0de0ch
- call cs:v32_vcpientryaddr ; n.b. this is a FAR call
-
- s32_int3_d:
- mov ax,18h
- mov gs,ax
- mov ax,10h
- mov ds,ax
- mov es,ax
- mov fs,ax
- mov ss,ax
- mov esp,s32_SavStackOfs
- pop s32_SavStackOfs
- mov ebx,s32_tssesp0ptr
- pop dword ptr [ebx]
- mov bx,V86F
-
- ;-----------------------------------------------------------------------------
- s32_int3_d2: ; done with INT32/33 from real or V86
- add nextmodestack,STACKSLOT*16
- mov ax,[esp+40]
- and ax,not 8d5h
- and bx,8d5h
- or ax,bx
- mov [esp+40],ax
- popad
- iretd
-
- ;------------------------------------------------------------------------
- ; exceptions handlers: some are terminal, others are redirected
- ; to the irq handler.
-
- ; exceptions 0..7 are reflected to the real mode interrupts 0..7
- s32_exc0:
- mov byte ptr ss:s32_irq_num,0
- jmp s32_irq
- s32_exc1:
- mov byte ptr ss:s32_irq_num,1
- jmp s32_irq
- s32_exc2:
- mov byte ptr ss:s32_irq_num,2
- jmp s32_irq
- s32_exc3:
- mov byte ptr ss:s32_irq_num,3
- jmp s32_irq
- s32_exc4:
- mov byte ptr ss:s32_irq_num,4
- jmp s32_irq
- s32_exc5:
- mov byte ptr ss:s32_irq_num,5
- jmp s32_irq
- s32_exc6:
- mov byte ptr ss:s32_irq_num,6
- jmp short s32_exc
- s32_exc7:
- mov byte ptr ss:s32_irq_num,7
- jmp s32_irq
-
- ; exceptions 8..0Fh produces program termination
- ; maybe in a future release i will support
- ; a core dumper for post mortem debug
- s32_exc8:
- pushad
- mov al,8
- jmp short s32_exc
- s32_exc9:
- pushad
- mov al,9
- jmp short s32_exc
- s32_exca:
- pushad
- mov al,0ah
- jmp short s32_exc
- s32_excb:
- pushad
- mov al,0bh
- jmp short s32_exc
- s32_excc:
- pushad
- mov al,0ch
- jmp short s32_exc
- s32_excd: ; general protection violation
- pushad
- mov al,0dh
- jmp s32_exc
- s32_exce:
- pushad
- mov al,0dh
- jmp short s32_exc
- s32_excf:
- pushad
- mov al,0FFh ; GENERIC failure
- ;-----------------------------------------------------------------------------
- s32_exc: ; main exception handler
- ; on entry al=error code (not used)
-
- mov ax,10h ; set up descriptors for termination
- mov ds,ax ;
- mov es,ax ;
- mov fs,ax ;
- mov gs,_SelZero ;
- cld
- jmp _Exit ; TERMINATE PROGRAM
-
- ; IRQ redirector between modes
-
- s32_irq0:
- mov byte ptr ss:s32_irq_num,8
- jmp s32_irq
- s32_irq1:
- mov byte ptr ss:s32_irq_num,9
- jmp s32_irq
- s32_irq2:
- mov byte ptr ss:s32_irq_num,0ah
- jmp s32_irq
- s32_irq3:
- mov byte ptr ss:s32_irq_num,0bh
- jmp short s32_irq
- s32_irq4:
- mov byte ptr ss:s32_irq_num,0ch
- jmp short s32_irq
- s32_irq5:
- mov byte ptr ss:s32_irq_num,0dh
- jmp short s32_irq
- s32_irq6:
- mov byte ptr ss:s32_irq_num,0eh
- jmp short s32_irq
- s32_irq7:
- mov byte ptr ss:s32_irq_num,0fh
- jmp short s32_irq
- s32_irq8:
- mov byte ptr ss:s32_irq_num,70h
- jmp short s32_irq
- s32_irq9:
- mov byte ptr ss:s32_irq_num,71h
- jmp short s32_irq
- s32_irqa:
- mov byte ptr ss:s32_irq_num,72h
- jmp short s32_irq
- s32_irqb:
- mov byte ptr ss:s32_irq_num,73h
- jmp short s32_irq
- s32_irqc:
- mov byte ptr ss:s32_irq_num,74h
- jmp short s32_irq
- s32_irqd:
- mov byte ptr ss:s32_irq_num,75h
- jmp short s32_irq
- s32_irqe:
- mov byte ptr ss:s32_irq_num,76h
- jmp short s32_irq
- s32_irqf:
- mov byte ptr ss:s32_irq_num,77h
- ;-----------------------------------------------------------------------------
- ; generic IRQ handler, al =INT to call if V86 routine has to be called
- ;
- s32_irq: ; select IRQ type: real->v86 or p->v86
- ; this is a real mode IRQ happened while in protected mode
- push ds
- push es
- push fs
- push gs
-
- pushfd
- push cs
- push offset s32_irqpd
- pushad
- mov ax,ss
- mov ds,ax
- mov gs,_SelZero
- mov ecx,s32_irq_num
- mov ebp,offset s16_irqreal
- jmp s32_16common
- s32_irqpd:
- pop gs
- pop fs
- pop es
- pop ds
- iretd
-
- ; Custom get IRQ handler offset
- ; In:
- ; BL - IRQ num (0-0fh)
- ; Out:
- ; EDX - offset of current IRQ handler
- s32_getirq:
- push ebx
- pushf
- cli
- movzx ebx,bl ;
- mov bl,intslotnum[ebx] ;
- lea ebx,[ebx*8] ; get location in IDT table
- add ebx,s32_idt32ptr
- mov dx,[ebx+6] ;
- shl edx,16 ; read ISR offset from IDT
- mov dx,[ebx] ;
- popf
- pop ebx
- ret
-
- ; Custom set IRQ handler offset
- ; In:
- ; BL - IRQ num (0-0fh)
- ; EDX - offset of new IRQ handler
- s32_setirq:
- pushad
- pushf
- cli
- movzx ebx,bl ;
- mov bl,[ebx+intslotnum] ;
- lea ebx,[ebx*8] ; get location in IDT table
- add ebx,s32_idt32ptr ;
- mov [ebx],dx ; modify descriptor for
- shr edx,16 ; new 32bit offset & same segment
- mov [ebx+6],dx ;
- popf
- popad
- ret
-
- code32 ends
-
- ; End of program
- ; (codeend segment must be at end of program or you will get lots of pain)
-
- codeend segment para stack use32 'stack'
- db STACKSIZE*16 dup(?)
- ; Stack Starts here
- codeend ends
- end Boot16
-
-